
package cn.com.bluemoon.daps.model.controller;

import cn.com.bluemoon.common.KeyAnnotationClz;
import cn.com.bluemoon.common.UserPermission;
import cn.com.bluemoon.common.permission.ModelEdit;
import cn.com.bluemoon.daps.api.sys.RemoteSystemDatasourceService;
import cn.com.bluemoon.daps.api.sys.RemoteSystemInfoService;
import cn.com.bluemoon.daps.api.sys.RemoteSystemTagsService;
import cn.com.bluemoon.daps.common.datascope.BmPermission;
import cn.com.bluemoon.daps.common.datascope.log.OperateLog;
import cn.com.bluemoon.daps.common.datascope.log.enums.ModuleObject;
import cn.com.bluemoon.daps.common.datascope.log.enums.OperateType;
import cn.com.bluemoon.daps.common.domain.ResultBean;
import cn.com.bluemoon.daps.common.enums.BmStatus;
import cn.com.bluemoon.daps.common.enums.DatabaseType;
import cn.com.bluemoon.daps.common.enums.SystemType;
import cn.com.bluemoon.daps.common.exception.DapException;
import cn.com.bluemoon.daps.common.toolkit.CheckUtils;
import cn.com.bluemoon.daps.model.dto.*;
import cn.com.bluemoon.daps.model.entity.*;
import cn.com.bluemoon.daps.model.service.*;
import cn.com.bluemoon.daps.model.utils.factory.impl.table.AbsTableScript;
import cn.com.bluemoon.daps.model.utils.factory.impl.table.HiveTableScript;
import cn.com.bluemoon.daps.model.utils.factory.impl.table.MysqlTableScript;
import cn.com.bluemoon.daps.model.utils.factory.impl.table.PostgreTableScript;
import cn.com.bluemoon.daps.model.vo.*;
import cn.com.bluemoon.daps.standard.api.RemoteStandardDataTypeService;
import cn.com.bluemoon.daps.standard.api.RemoteSystemCategoryService;
import cn.com.bluemoon.daps.standard.entity.DapStandardDataType;
import cn.com.bluemoon.daps.standard.entity.DapSystemCategory;
import cn.com.bluemoon.daps.system.entity.DapSystemDatasource;
import cn.com.bluemoon.daps.system.entity.DapSystemInfo;
import cn.com.bluemoon.daps.system.entity.DapSystemTag;
import cn.com.bluemoon.metadata.inter.MetaDataSchemaService;
import cn.com.bluemoon.metadata.inter.dto.out.HiveSchemaInfoVO;
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import reactor.util.function.Tuple2;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@Slf4j
@RequestMapping("/dapModel")
@Api(tags = {"模型管理"})
@Validated
public class DapModelController {

    @Resource
    DapDataModelService dapDataModelService;

    @Resource
    RemoteSystemInfoService dapSystemInfoService;

    @Resource
    RemoteSystemTagsService dapSystemTagService;

    @Resource
    DapDataModelTableService dapDataModelTableService;

    @Resource
    DapDataModelTableFieldService dapDataModelTableFieldService;

    @Resource
    DapDataModelSubordinateKeyService dapDataModelSubordinateKeyService;

    @Resource
    DapDataModelTablePartitionService dapDataModelTablePartitionService;

    @Resource
    DapDataModelRelatedStandardResultService dapDataModelRelatedStandardResultService;

    @Resource
    RemoteSystemCategoryService dapSystemCategoryService;

    @Resource
    DapDataModelRecordService dapDataModelRecordService;

    @Resource
    DapDataModelJsonService dapDataModelJsonService;

    @Resource
    RemoteSystemDatasourceService dapSystemDatasourceService;

    @Resource
    DapDataModelTableForeignKeyService dapDataModelTableForeignKeyService;

    @Resource
    RemoteStandardDataTypeService remoteStandardDataTypeService;

    @Resource
    MetaDataSchemaService metaDataSchemaService;

    @Resource
    DapDataModelShareTableService dapDataModelShareTableService;


    /**
     *
     * @param vo v1.2 ok
     * @return
     */

    @BmPermission(value = "model:list", name = "模型列表查询")
    @PostMapping("model/pageList")
    @ApiOperation(value = "获取模型分页列表，带模糊搜索")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ModelInfoDto.class)})
    @OperateLog(type = OperateType.SELECT, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<IPage<ModelInfoDto>> getModelList(@RequestBody @Valid DataModelPageVo vo){

        IPage<ModelInfoDto> modelList = dapDataModelService.getModelList(vo);
        return ResultBean.ok(modelList);

    }

    @BmPermission(value = "model:list", name = "模型列表查询")
    @GetMapping("system/modelList")
    @ApiOperation(value = "导入模型表-获取系统下的模型列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ModelInfoDto.class)})
    public ResultBean<List<DapDataModel>> getSystemModelList(@RequestParam("systemId") String systemId,
                                                             @RequestParam("modelId") String modelId){

        List<DapDataModel> list = dapDataModelService.getModelListById(systemId);
        // 剔除当前模型
        List<DapDataModel> collect = list.stream().filter(d -> !d.getId().equals(modelId)).collect(Collectors.toList());
        return ResultBean.ok(collect);

    }

    @BmPermission(value = "model:table:list", name = "模型列表查询")
    @GetMapping("model/tableList")
    @ApiOperation(value = "导入模型表-获取模型下的表列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ModelInfoDto.class)})
    public ResultBean<List<DapDataModelTable>> getModelTableList(@RequestParam("modelId") String modelId){

        LambdaQueryWrapper<DapDataModelTable> wrapper = new LambdaQueryWrapper();
        List<DapDataModelTable> tables = dapDataModelTableService.getBaseMapper()
                .selectList(wrapper.select(DapDataModelTable::getId, DapDataModelTable::getEngName)
                        .eq(DapDataModelTable::getDataModelId, modelId).eq(DapDataModelTable::getBmStatus, BmStatus.ON.getCode())
                        .eq(DapDataModelTable::getPId,"0"));
        return ResultBean.ok(tables);

    }

    @BmPermission(value = "model:table:list", name = "模型列表查询")
    @GetMapping("mysql/model/List")
    @ApiOperation(value = "查询mysql类型的模型")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = List.class)})
    public ResultBean<List<DapDataModel>> mysqlModelList(){

        // 查询为mysql的数据源
        ResultBean<List<DapSystemDatasource>> resultBean = dapSystemDatasourceService.getDatasourceByDatabaseType(DatabaseType.MYSQL);
        if(resultBean.getCode() == 200 && !resultBean.getContent().isEmpty()){
            List<DapSystemDatasource> content = resultBean.getContent();
            List<String> collect = content.stream().map(DapSystemDatasource::getId).collect(Collectors.toList());
            // 查询绑定的模型
            LambdaQueryWrapper<DapDataModel> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(DapDataModel::getDataSourceId, collect).eq(DapDataModel::getBmStatus, BmStatus.ON.getCode());
            List<DapDataModel> dapDataModels = dapDataModelService.getBaseMapper().selectList(wrapper);
            return ResultBean.ok(dapDataModels);
        }
        return resultBean.getCode() == 500 ? ResultBean.error(resultBean.getMsg()) : ResultBean.ok(null);

    }

    @BmPermission(value = "model:list", name = "模型列表查询")
    @GetMapping("system/dataHouse/model")
    @ApiOperation(value = "新建维度-获取数仓系统下模型列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ModelInfoDto.class)})
    public ResultBean<List<DapDataModel>> getDataHouseSystemModelList(@RequestParam("systemId") String systemId){

        List<DapDataModel> list = dapDataModelService.getModelListById(systemId);
        return ResultBean.ok(list);
    }

    @BmPermission(value = "model:table:list", name = "模型列表查询")
    @GetMapping("model/dim/table")
    @ApiOperation(value = "维度管理-获取数仓模型下的维度表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ModelInfoDto.class)})
    public ResultBean<List<DapDataModelTable>> getDimModelTableList(@RequestParam("modelId") String modelId){

        LambdaQueryWrapper<DapDataModelTable> wrapper = new LambdaQueryWrapper();
        List<DapDataModelTable> tables = dapDataModelTableService.getBaseMapper()
                .selectList(wrapper.select(DapDataModelTable::getId, DapDataModelTable::getEngName)
                        .eq(DapDataModelTable::getDataModelId, modelId).eq(DapDataModelTable::getBmStatus, BmStatus.ON.getCode())
                        .eq(DapDataModelTable::getPId,"0").eq(DapDataModelTable::getTableCategory, 1));
        return ResultBean.ok(tables);

    }

    @BmPermission(value = "model:list", name = "模型列表查询")
    @GetMapping("register/modelList")
    @ApiOperation(value = "注册管理-查询已经注册的模型")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapDataModel.class)})
    public ResultBean<List<DapDataModel>> getRegisterModel(){

        List<DapDataModel> dapDataModels = dapDataModelService.getBaseMapper().selectList(new LambdaQueryWrapper<DapDataModel>()
                .eq(DapDataModel::getBmStatus, BmStatus.ON.getCode()));
        return ResultBean.ok(dapDataModels);
    }

    /**
     *
     * @param vo v1.2 ok
     * @return
     */
    @BmPermission(value = "model:add", name = "新增模型")
    @PostMapping("model/insert")
    @ApiOperation(value = "新增模型")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @OperateLog(type = OperateType.INSERT, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<Boolean> insertModel(@RequestBody @Valid DataModelInsertVo vo){

        // 判断模型名称是否重复
        List<DapDataModel> modelById = dapDataModelService.getBaseMapper()
                .selectList(new LambdaQueryWrapper<DapDataModel>()
                .eq(DapDataModel::getName, vo.getDapDataModel().getName())
                .eq(DapDataModel::getBmStatus, BmStatus.ON.getCode()));
        if(!modelById.isEmpty()) { return ResultBean.error("模型名称重复"); }
        return ResultBean.ok(dapDataModelService.insertModel(vo));
    }

    /**
     *
     * @param modelId v1.2 ok
     * @param
     * @return
     */
    @BmPermission(value = "model:info", name = "查看模型")
    @GetMapping("model/lookup")
    @ApiOperation(value = "查看模型")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Map.class)})
    public ResultBean<Map<String, Object>> getModel(@ApiParam("模型id") @RequestParam String modelId){

        // 查询模型是否可编辑
        boolean isEdit = dapDataModelRecordService.getUnRelease(modelId);
        // 模型信息
        DapDataModel modelById = dapDataModelService.getModelById(modelId);
        // 一个模型只能被一个系统使用
        ResultBean<DapSystemInfo> systemInfo = dapSystemInfoService.getSystemInfo(modelById.getSystemId());
        // 根据数据源id查询数据源信息
        ResultBean<DapSystemDatasource> datasource = dapSystemDatasourceService.getDatasource(modelById.getDataSourceId());
        // 根据模型id获得关联的系统标签
        ResultBean<List<DapSystemTag>> tags = dapSystemTagService.getTags(modelId, 0);
        // 封装结果集
        Map<String, Object> map = new HashMap<>();
        map.put("dapDataModel",modelById);
        map.put("dapSystemInfo",systemInfo.getContent());
        map.put("datasource",datasource.getContent());
        map.put("DapSystemTagList",tags.getContent());
        return ResultBean.ok(map).addMoreData("isEdit", isEdit);

    }

    /**
     *
     * @param modelId v1.2 ok
     * @param
     * @return
     */
    @BmPermission(value = "model:info", name = "获取模型名称")
    @GetMapping("model/name")
    @ApiOperation(value = "获取模型名称")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = String.class)})
    public ResultBean<String> getModelName(@ApiParam("modelId") @RequestParam String modelId){

        DapDataModel dapDataModel = dapDataModelService.getBaseMapper().selectById(modelId);
        return dapDataModel == null ? ResultBean.error("该模型不存在") : ResultBean.ok(dapDataModel.getName());
    }

    /**
     * 保存模型
     * @param vo v1.2 ok
     * @return
     */
    @BmPermission(value = "model:modify", name = "保存模型")
    @PostMapping("model/modify")
    @ApiOperation(value = "保存模型")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, errorMsg = "只允许模型授权者进行编辑模型功能")
    @ModelEdit(keyFormClz = KeyAnnotationClz.RequestBody)
    @OperateLog(type = OperateType.UPDATE, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<Boolean> modifyModel(@RequestBody @Valid DataModelInsertVo vo) {

        // 根据模型名查询
        DapDataModel dapDataModel = dapDataModelService.getBaseMapper()
                .selectOne(new LambdaQueryWrapper<DapDataModel>()
                .eq(DapDataModel::getName, vo.getDapDataModel().getName())
                .eq(DapDataModel::getBmStatus, BmStatus.ON.getCode()));
        boolean isEdit = dapDataModel == null || dapDataModel.getId().equals(vo.getDapDataModel().getId());
        return isEdit ? dapDataModelService.modifyModel(vo):ResultBean.error("模型名重复请重新输入");

    }

    /**
     * 删除模型
     * @param modelId v1.2 ok
     * @return
     */
    @BmPermission(value = "model:delete", name = "删除模型")
    @DeleteMapping("model/delete")
    @ApiOperation(value = "删除模型")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @UserPermission.SingleRow(key = "modelId", keyFormClz = KeyAnnotationClz.RequestParam, errorMsg = "只允许模型授权者进行删除模型功能")
    @ModelEdit(keyFormClz = KeyAnnotationClz.RequestParam, errorMsg = "当前模型处于发布流程中，不允许删除")
    @OperateLog(type = OperateType.DELETE, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<Boolean> deleteModel(@ApiParam("模型id") @RequestParam String modelId) {

        // 查询模型下面是否有数据表
        List<DapDataModelTable> dapDataModelTables = dapDataModelTableService.getBaseMapper()
                .selectList(new LambdaQueryWrapper<DapDataModelTable>()
                .eq(DapDataModelTable::getDataModelId, modelId)
                .eq(DapDataModelTable::getBmStatus, BmStatus.ON.getCode())
                .eq(DapDataModelTable::getPId,'0'));
        return dapDataModelTables.isEmpty() ? dapDataModelService.deleteModel(modelId) : ResultBean.error("模型下存在数据表，不允许删除");
    }

    /**
     * 模型表查询
     * @param idVo v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:list", name = "模型表查询")
    @PostMapping("modelTable/list")
    @ApiOperation(value = "模型中表的列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = TableListDto.class)})
    public ResultBean<List<TableListDto>> getModelTableList(@RequestBody IdVo idVo) {

        // 是否允许修改
        Boolean isEdit = dapDataModelRecordService.getUnRelease(idVo.getModelId());
        // 当前模型
        if(idVo.getIsCurrentModel()){
            List<TableListDto> modelTableList = dapDataModelTableService.getTableByGroupId(idVo);
            // 获得分组表的id
            List<String> collect = modelTableList.stream().map(TableListDto::getTableId).collect(Collectors.toList());
            List<DapDataModelTableForeignKey> keyList = new ArrayList<>();
            if(idVo.getIsEr()){
                // 根据模型id获得模型下的所有外键关系
                List<DapDataModelTableForeignKey> keys = dapDataModelTableForeignKeyService.getBaseMapper()
                                .selectList(new LambdaQueryWrapper<DapDataModelTableForeignKey>()
                                .eq(DapDataModelTableForeignKey::getBmStatus, BmStatus.ON.getCode())
                                .eq(DapDataModelTableForeignKey::getModelId, idVo.getModelId()));
                // 当前分组的外键关系
                keyList = keys.stream().filter(k -> collect.contains(k.getModelTableId())).collect(Collectors.toList());
                // 获得该表以及引用表的的字段id
                List<String> fieldIds = keyList.stream().flatMap(d -> Arrays.asList(d.getModelTableFieldId(), d.getReferenceFieldId()).stream())
                        .collect(Collectors.toList());
                if(!fieldIds.isEmpty()){
                    List<DapDataModelTableField> fields = dapDataModelTableFieldService.getBaseMapper().selectBatchIds(fieldIds);
                    Map<String, String> map = fields.stream().collect(Collectors.toMap(DapDataModelTableField::getId, DapDataModelTableField::getFieldName));
                    for(DapDataModelTableForeignKey key:keyList){
                        if (map.containsKey(key.getModelTableFieldId())) {
                            key.setFieldName(map.get(key.getModelTableFieldId()));
                        }
                        if (map.containsKey(key.getReferenceFieldId())) {
                            key.setReferenceFieldName(map.get(key.getReferenceFieldId()));
                        }
                        key.setRelationName(String.format("%s->%s(%s)", key.getFieldName(), key.getReferenceFieldName(), key.getRelation()));
                    }
                }
                // 获得其他分组表id
                List<String> unGroupTableId = keyList.stream().filter(k -> !collect.contains(k.getReferenceTableId()))
                        .map(DapDataModelTableForeignKey::getReferenceTableId).collect(Collectors.toList());
                // 如果其他分组表id不为空
                if(!unGroupTableId.isEmpty()){
                    IdVo id = new IdVo();
                    id.setTableId(unGroupTableId);
                    List<TableListDto> table = dapDataModelTableService.getTableByGroupId(id);
                    List<TableListDto> unGroupTableList = table.stream().peek(t -> t.setIsGroup(false)).collect(Collectors.toList());
                    modelTableList.addAll(unGroupTableList);
                }
            }
            List<TableListDto> arrayList = modelTableList.stream().peek(t -> { t.setDataSourceId(null);t.setUpdateTime(null);}).collect(Collectors.toList());
            return ResultBean.ok(arrayList).addMoreData("isEdit", isEdit).addMoreData("keys", keyList);
        }else{ // 共享模型
            List<DapDataModelShareTable> list = dapDataModelShareTableService.getBaseMapper().selectList(new LambdaQueryWrapper<DapDataModelShareTable>()
                    .eq(DapDataModelShareTable::getModelId, idVo.getModelId()));
            List<String> tableIds = list.stream().map(DapDataModelShareTable::getTableId).collect(Collectors.toList());
            idVo.setTableId(tableIds);
            List<TableListDto> modelTableList = dapDataModelTableService.getTableByGroupId(idVo);
            return ResultBean.ok(modelTableList).addMoreData("isEdit", isEdit).addMoreData("keys", null);
        }
    }

    @BmPermission(value = "model:table:list", name = "模型表查询")
    @PostMapping("table/info")
    @ApiOperation(value = "单个表信息及字段")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = TableListDto.class)})
    public ResultBean<TableListDto> getSingleTable(@RequestParam("tableId") String tableId) {

        IdVo idVo = new IdVo();
        idVo.setTableId(Arrays.asList(tableId));
        List<TableListDto> tableByGroupId = dapDataModelTableService.getTableByGroupId(idVo);
        if(tableByGroupId.isEmpty()){
            return ResultBean.error("获得表信息失败");
        }
        return ResultBean.ok(tableByGroupId.get(0));
    }
        /**
     * 表基本信息
     * @param modelTableId v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:info", name = "表基本信息")
    @GetMapping("modelTable/info")
    @ApiOperation(value = "模型中表的详情")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Map.class)})
    public ResultBean<Map<String, Object>> getModelTableInfo(@RequestParam @ApiParam("模型中表id")
                                                             @NotNull(message = "模型中表id不允许为空") String modelTableId) {

        DapDataModelTable dapDataModelTable = dapDataModelTableService.getModelTableById(modelTableId);
        ResultBean<List<DapSystemCategory>> dapSystemCategories = null;
        Map<String, Object> map = new HashMap<>();
        if(null != dapDataModelTable && StringUtils.isNotBlank(dapDataModelTable.getCategoryId())){
            // 查询分类详情
            List<String> strings = Arrays.asList(dapDataModelTable.getCategoryId().split(","));
            dapSystemCategories = dapSystemCategoryService.getSystemCategories(strings);
            map.put("dapSystemCategories", dapSystemCategories.getContent() == null ? null : dapSystemCategories.getContent());
        }
        ResultBean<List<DapSystemTag>> dapSystemTags = dapSystemTagService.getTags(modelTableId, 1);
        map.put("dapDataModelTable",dapDataModelTable);
        map.put("dapSystemTags", dapSystemTags.getContent());
        return ResultBean.ok(map);
    }

    /**
     * 新增或修改模型中表
     * @param vo v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @PostMapping("modelTable/insert")
    @ApiOperation(value = "新增或修改模型中表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = String.class)})
    @OperateLog(type = OperateType.UPDATE, moduleName = ModuleObject.DATA_MODEL)
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, errorMsg = "只允许模型授权者进行修改模型中表")
    @ModelEdit(keyFormClz = KeyAnnotationClz.RequestBody)
    public ResultBean<String> insertModelTable(@RequestBody @Valid DataModelTableInsertVO vo){

        ResultBean<String> stringResultBean = dapDataModelTableService.insertModelTable(vo);
        return stringResultBean;
    }

    /**
     * 删除模型中的表(可批量)
     * @param id v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:delete", name = "删除模型表")
    @DeleteMapping("modelTable/delete")
    @ApiOperation(value = "删除模型中的表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestParam, key = "modelId", errorMsg = "只允许模型授权者进行删除模型中表")
    @ModelEdit(key = "modelId", keyFormClz = KeyAnnotationClz.RequestParam)
    @OperateLog(type = OperateType.DELETE, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<Boolean> deleteModelTable(@RequestParam("id") @ApiParam("模型中的表id") String id,
                                                @RequestParam("modelId") String modelId,
                                                @RequestParam("dataType") @ApiParam("数据库类型，1 mysql 2 pg 3 hive") Integer dataType){

        // 查询模型信息
        DapDataModel dapDataModel = dapDataModelService.getBaseMapper().selectById(modelId);
        // 查询数据库类型
        ResultBean<DapSystemDatasource> datasource = dapSystemDatasourceService.getDatasource(dapDataModel.getDataSourceId());
        if(datasource.getCode() == 200){
            Boolean aBoolean = dapDataModelTableService.deleteTableAll(id,datasource.getContent().getDatabaseType());
            return aBoolean ? ResultBean.ok(aBoolean) : ResultBean.error(String.format("表%s不存在, 删除失败", id));
        }
        return ResultBean.error("删除表失败！");
    }

    /**
     * 编辑模型表
     * @param id v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @PostMapping("modelTable/field/detail")
    @ApiOperation(value = "字段详细信息表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = FieldStandardDto.class)})
    @OperateLog(type = OperateType.SELECT, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<List<FieldStandardDto>> fieldDetail(@RequestParam("id") @ApiParam("模型中的表id") @NotNull(message = "模型表id不能为空") String id){

        // 判断表是否存在
        DapDataModelTable table = dapDataModelTableService.getBaseMapper().selectById(id);
        if(table == null || table.getBmStatus().equals(BmStatus.DELETE)){
            return ResultBean.error("字段数据不存在");
        }
        // 根据模型中的表id获得字段信息
        List<FieldStandardDto> fieldList = dapDataModelTableFieldService.getFieldList(id);
        return ResultBean.ok(fieldList);
    }

    /**
     * 新增字段
     * @param fields v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @PostMapping("modelTable/field/insert")
    @ApiOperation(value = "新增字段")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, errorMsg = "只允许模型授权者新增模型中表字段")
    @ModelEdit(keyFormClz = KeyAnnotationClz.RequestBody)
    @Transactional(rollbackFor = {DapException.class, RuntimeException.class})
    @OperateLog(type = OperateType.UPDATE, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<Boolean> insertField(@RequestBody @Valid InsertModelTableFieldVo fields){

        if(!fields.getFields().isEmpty()){
            List<String> fieldName = fields.getFields().stream().map(DapDataModelTableField::getFieldName).collect(Collectors.toList());
            // 所有数据库不区分大小写
            List<String> collect = fieldName.stream().map(f -> f.toLowerCase()).collect(Collectors.toList());
            List<String> duplicateElements = CheckUtils.getDuplicateElements(collect);
            // 校验字段类型是否符合当前数据库类型
            DapDataModel dapDataModel = dapDataModelService.getBaseMapper().selectById(fields.getFields().get(0).getDataModelId());
            // 查询数据源
            ResultBean<DapSystemDatasource> datasource = dapSystemDatasourceService.getDatasource(dapDataModel.getDataSourceId());
            if(datasource.getContent()==null){
                return ResultBean.error("数据源信息获取失败，无法校验列表字段类型的正确性");
            }
            List<String> dataType = fields.getFields().stream()
                    .map(DapDataModelTableField::getDataType).collect(Collectors.toList());
            ResultBean<List<DapStandardDataType>> dataTypeByDbType = remoteStandardDataTypeService.getDataTypeByDbType(datasource.getContent().getDatabaseType().getCode());
            if(dataTypeByDbType.getContent() == null){
                return ResultBean.error("获取数据类型失败");
            }
            List<String> codes = dataTypeByDbType.getContent().stream().map(DapStandardDataType::getCode).collect(Collectors.toList());
            List<String> noMatch = dataType.stream().filter(t -> !codes.contains(t)).collect(Collectors.toList());
            if(noMatch.isEmpty()){
                if(duplicateElements.isEmpty()){
                    return dapDataModelTableFieldService.insertField(fields, datasource.getContent().getDatabaseType());
                }
                return ResultBean.error(duplicateElements.toString()+"字段名重复，请修改后重新提交！");
            };
            return ResultBean.error("字段数据类型"+noMatch.toString()+"与当前数据库不匹配");
        }
        return ResultBean.error("字段列表为空！请添加数据");
    }

    /**
     * 删除字段(可批量)
     * @param deleteFieldVo v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @DeleteMapping("modelTable/field/delete")
    @ApiOperation(value = "删除字段(可批量)")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, errorMsg = "只允许模型授权者进行删除模型中表字段")
    @ModelEdit(keyFormClz = KeyAnnotationClz.RequestBody)
    @Transactional(rollbackFor = {DapException.class, RuntimeException.class})
    @OperateLog(type = OperateType.DELETE, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<Boolean> deleteField(@RequestBody DeleteFieldVo deleteFieldVo){

        // 用于存储被引用的字段id
        List<String> ids = new ArrayList<>();
        // 数据库为mysql和pg
        if(deleteFieldVo.getDatabaseType() != DatabaseType.HIVE){
            // 查询该表下所有的索引信息
            List<DapDataModelSubordinateKey> keys = dapDataModelSubordinateKeyService.getBaseMapper()
                    .selectList(new LambdaQueryWrapper<DapDataModelSubordinateKey>()
                            .eq(DapDataModelSubordinateKey::getModelTableId, deleteFieldVo.getModelTableId())
                            .eq(DapDataModelSubordinateKey::getBmStatus, BmStatus.ON.getCode()));
            String collect = keys.stream().map(DapDataModelSubordinateKey::getFieldIds).collect(Collectors.joining());
            ids = deleteFieldVo.getIds().stream().filter(s -> collect.contains(s)).collect(Collectors.toList());
        }
        if(ids.isEmpty()){
            // 批量删除数据
            List<DapDataModelTableField> list = new ArrayList<>();
            deleteFieldVo.getIds().forEach(id->{
                DapDataModelTableField dapDataModelTableField = new DapDataModelTableField();
                dapDataModelTableField.setId(id);
                dapDataModelTableField.setBmStatus(BmStatus.DELETE);
                list.add(dapDataModelTableField);
            });
            boolean b = dapDataModelTableFieldService.updateBatchById(list);
            // 字段重新排序
            dapDataModelTableFieldService.fieldRank(deleteFieldVo.getModelTableId());
            // 查询该表的字段的外键关系
            dapDataModelTableForeignKeyService.delForeignKey(deleteFieldVo.getModelTableId(), ids);
            // 刷新表更新时间
            dapDataModelTableService.saveTime(deleteFieldVo.getModelTableId());
            // 同时删除引用标准的记录
            return ResultBean.ok(b);
        }else {
            return ResultBean.error(ids.toString() + "字段被索引引用，无法删除！");
        }
    }

    /**
     * mysql和 pg 才有索引功能
     * @param id v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @GetMapping("modelTable/key/detail")
    @ApiOperation(value = "索引列表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = SubordinateKeyDto.class)})
    public ResultBean<List<SubordinateKeyDto>> keyList(@RequestParam @ApiParam("模型中的表id") String id){

        List<SubordinateKeyDto> keyList = dapDataModelSubordinateKeyService.getKeyList(id);
        return ResultBean.ok(keyList);
    }

    /**
     * mysql和 pg 才有索引功能
     * @param vo v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @PostMapping("modelTable/key/insert")
    @ApiOperation(value = "新增或修改索引")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, errorMsg = "只允许模型授权者进行修改模型中表索引")
    @Transactional(rollbackFor = {DapException.class, RuntimeException.class})
    @ModelEdit(keyFormClz = KeyAnnotationClz.RequestBody)
    @OperateLog(type = OperateType.UPDATE, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<Boolean> insertKey(@RequestBody @Valid InsertModelKeyVo vo){

        if(!vo.getKeys().isEmpty()){
            // 索引名不允许重复
            List<String> repeat = dapDataModelSubordinateKeyService.isRepeat(vo.getKeys());
            if (!repeat.isEmpty()){
                return ResultBean.error(repeat.toString()+"索引名重复！");
            }
            // 索引引用的字段不允许相同
            List<String> ids = vo.getKeys().stream().map(DapDataModelSubordinateKey::getFieldIds).collect(Collectors.toList());
            if(!CheckUtils.getDuplicateElements(ids).isEmpty()){
                return ResultBean.error("索引引用的字段不可重复！");
            }
            ResultBean result = dapDataModelSubordinateKeyService.insertKey(vo.getKeys(), vo.getDatabaseType());
            // 刷新表更新时间
            dapDataModelTableService.saveTime(vo.getKeys().get(0).getModelTableId());
            return result;
        }else {
            return ResultBean.error("索引列表为空！请添加数据");
        }
    }

    /**
     * mysql和 pg 才有索引功能
     * @param ids v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @DeleteMapping("modelTable/key/delete")
    @ApiOperation(value = "删除索引(可批量)")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, errorMsg = "只允许模型授权者进行修改模型中表索引")
    @OperateLog(type = OperateType.DELETE, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<Boolean> deleteKey(@RequestBody @ApiParam("索引id") @Valid DeleteByIds ids){

        DapDataModelTable table = dapDataModelTableService.getBaseMapper().selectById(ids.getTableId());
        if(table == null){
            return ResultBean.error("表不存在，无法删除索引");
        }
        if(!dapDataModelRecordService.getUnRelease(table.getDataModelId())){
            return ResultBean.error("当前表处于发布流程，不允许删除");
        };
        List<DapDataModelSubordinateKey> list = new ArrayList<>();
        ids.getIds().forEach(id->{
            DapDataModelSubordinateKey dapDataModelSubordinateKey = new DapDataModelSubordinateKey();
            dapDataModelSubordinateKey.setId(id);
            dapDataModelSubordinateKey.setBmStatus(BmStatus.DELETE);
            list.add(dapDataModelSubordinateKey);
        });
        boolean b = dapDataModelSubordinateKeyService.updateBatchById(list);
        // 刷新表更新时间
        dapDataModelTableService.saveTime(ids.getTableId());
        return ResultBean.ok(b);
    }

    /**
     * hive模型具备此功能
     * @param id v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @GetMapping("modelTable/partition/list")
    @ApiOperation(value = "获得分区列表信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = DapDataModelTablePartition.class)})
    public ResultBean<List<DapDataModelTablePartition>> getTablePartition(@RequestParam @ApiParam("模型中的表id") String id){

        List<DapDataModelTablePartition> partitionList = dapDataModelTablePartitionService.getPartitionList(id);
        List<DapDataModelRecord> dapDataModelRecords = null;
        if(!partitionList.isEmpty()){
            String modelId = partitionList.get(0).getDataModelId();
            dapDataModelRecords = dapDataModelRecordService.getRecord(modelId);
        }
        return ResultBean.ok(partitionList).addMoreData("isEdit", dapDataModelRecords == null ? true : false);
    }

    /**
     * hive模型具备此功能
     * @param list v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @PostMapping("modelTable/partition/insert")
    @ApiOperation(value = "新增分区")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, errorMsg = "只允许模型授权者进行新增模型中表分区")
    @OperateLog(type = OperateType.INSERT, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<Boolean> insertTablePartition(@RequestBody @Valid InsertModelTablePartitionVo list){

        if(list.getPartitions().isEmpty()){
            return ResultBean.error("分区为空，请添加数据");
        }else {
            List<DapDataModelRecord> record = dapDataModelRecordService.getRecord(list.getPartitions().get(0).getDataModelId());
            if(!record.isEmpty()){
                return ResultBean.error("分区已发布，不允许编辑");
            }
        }
        List<String> names = list.getPartitions().stream().map(DapDataModelTablePartition::getPartitionFieldName).collect(Collectors.toList());
        // 所有数据库不区分大小写
        List<String> collect = names.stream().map(f -> f.toLowerCase()).collect(Collectors.toList());
        List<String> duplicateElements = CheckUtils.getDuplicateElements(collect);
        if(!duplicateElements.isEmpty()){
            return ResultBean.error("分区名重复"+duplicateElements.toString());
        }
        // 进行插入操作
        ResultBean result = dapDataModelTablePartitionService.insertPartition(list.getPartitions());
        // 更新时间
        dapDataModelTableService.saveTime(list.getPartitions().get(0).getModelTableId());
        return result;
    }

    /**
     * 删除分区列表(可批量)
     * @param ids v1.2 ok
     * @return
     */
    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @DeleteMapping("modelTable/partition/delete")
    @ApiOperation(value = "删除分区列表(可批量)")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, errorMsg = "只允许模型授权者进行删除模型中表分区")
    @OperateLog(type = OperateType.DELETE, moduleName = ModuleObject.DATA_MODEL)
    public ResultBean<Boolean> deletePartition(@RequestBody @ApiParam("分区id") @Valid DeleteByIds ids){

        // 获得模型id
        DapDataModelTable table = dapDataModelTableService.getBaseMapper().selectById(ids.getTableId());
        List<DapDataModelRecord> record = dapDataModelRecordService.getRecord(table.getDataModelId());
        if(!record.isEmpty()){
            return ResultBean.error("分区已发布，不允许删除");
        }
        List<DapDataModelTablePartition> list = new ArrayList<>();
        ids.getIds().forEach(id->{
            DapDataModelTablePartition dapDataModelTablePartition = new DapDataModelTablePartition();
            dapDataModelTablePartition.setId(id);
            dapDataModelTablePartition.setBmStatus(BmStatus.DELETE);
            list.add(dapDataModelTablePartition);
        });
        boolean b = dapDataModelTablePartitionService.updateBatchById(list);
        // 刷新表更新时间
        dapDataModelTableService.saveTime(ids.getTableId());
        return ResultBean.ok(b);
    }

    @BmPermission(value = "model:table:export", name = "模型表sql预览", ignore = true)
    @GetMapping("modelTable/sql/preview")
    @ApiOperation(value = "sql预览")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = String.class),
            @ApiResponse(code = 200, message = "ok", responseContainer = "list", response = String.class)})
    public ResultBean<List<String>> sqlPreView(@ApiParam("模型中的表id") @RequestParam String modelId,
                                               @ApiParam("模型中的表id") @RequestParam String tableId){
        Tuple2<DapDataModel, Optional<DatabaseType>> modelInfo = dapDataModelService.findModelAndDbTypeByModelId(modelId);
        DatabaseType databaseType = modelInfo.getT2().orElseThrow(() -> new DapException("模型所属数据库类型：未知！"));
        ModelIds request = new ModelIds();
        request.setDatabaseType(databaseType);
        request.setModelId(modelId);
        request.setTableId(tableId);
        List<String> sqlList = dapDataModelTableService.getCreateTableSqls(request);
        return ResultBean.ok(sqlList);
    }

    @BmPermission(value = "model:table:export", name = "模型表导出建表sql")
    @PostMapping("modelTable/sql/scan")
    @ApiOperation(value = "sql预览")
    @ApiResponses(value = {@ApiResponse(code = 500, message = "错误原因信息", response = String.class),
            @ApiResponse(code = 200, message = "ok", responseContainer = "list", response = String.class)})
    public ResultBean<List<String>> exportSql(@RequestBody @ApiParam("模型中的表id") @Valid ModelIds tables){
        List<String> sqlList = dapDataModelTableService.getCreateTableSqls(tables);
        return ResultBean.ok(sqlList);
    }

    @BmPermission(value = "model:table:export", name = "模型表导出建表sql")
    @PostMapping("modelTable/sql/download")
    @ApiOperation(value = "sql下载")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, key = "modelId", errorMsg = "只允许模型授权者进行下载建表语句功能")
    public void downloadSql(HttpServletResponse response, @RequestBody @ApiParam("模型中的表id") ModelIds modelIds){

        try {
            response.setHeader("Content-Disposition", "attachment;filename="
                    + new String(("model.sql").getBytes(), "iso-8859-1"));
            List<DapDataModelTable> list = dapDataModelTableService.getBaseMapper()
                    .selectList(new LambdaQueryWrapper<DapDataModelTable>()
                            .eq(DapDataModelTable::getDataModelId, modelIds.modelId)
                            .eq(DapDataModelTable::getBmStatus, BmStatus.ON.getCode())
                            .eq(DapDataModelTable::getPId, "0"));
            List<String> collect = list.stream().map(DapDataModelTable::getId).collect(Collectors.toList());
            OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream(), "utf-8");
            for (String modelTableId:collect) {
                // 根据模型表id查询数据库中的表和字段信息
                ModelTableInfoDto tableInfo = dapDataModelTableFieldService.getTableInfo(modelTableId);
                // 根据数据库类型获得sql
                if(modelIds.getDatabaseType().equals(DatabaseType.HIVE)){
                    // 根据模型表id获取分区信息
                    List<DapDataModelTablePartition> partitionList = dapDataModelTablePartitionService.getPartitionList(modelTableId);
                    HiveTableScript hiveTableScript = new HiveTableScript();
                    String hive = hiveTableScript.createTableScript(tableInfo, null, partitionList);
                    writer.write(hive + "\r\n");
                }else{
                    // 根据模型表id获取索引信息
                    List<SubordinateKeyDto> keyList = dapDataModelSubordinateKeyService.getKeyList(modelTableId);
                    AbsTableScript absTableScript = modelIds.getDatabaseType().equals(DatabaseType.MYSQL) ? new MysqlTableScript() : new PostgreTableScript();
                    String tableScript = absTableScript.createTableScript(tableInfo, keyList, null);
                    // 生成sql语句
                    writer.write(tableScript + "\r\n");
                }
            }
            writer.close();
        } catch (IOException e) {
            throw new DapException("下载失败");
        }
    }

    @BmPermission(value = "model:table:relation:standard", name = "关联标准")
    @PostMapping("modelTable/unRelation")
    @ApiOperation("未关联标准(分页)")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = UnRelationDto.class)})
    public ResultBean<IPage<UnRelationDto>> unRelationStandard(@RequestBody @Valid SearchRelationVo searchRelationVo){

        // 先查询模型是否删除
        DapDataModel model = dapDataModelService.getModelById(searchRelationVo.getDataModelId());
        if(model.getBmStatus().getCode() == -1){
            return ResultBean.error("模型已被删除");
        }
        IPage<UnRelationDto> unRelationPage = dapDataModelRelatedStandardResultService.getUnRelationPage(searchRelationVo);
        return ResultBean.ok(unRelationPage);
    }

    @BmPermission(value = "model:table:relation:standard", name = "关联标准")
    @PostMapping("modelTable/already/relation")
    @ApiOperation("已关联标准(分页)")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = UnRelationDto.class)})
    public ResultBean<IPage<UnRelationDto>> alreadyRelationStandard(@RequestBody @Valid SearchRelationVo searchRelationVo){

        // 先查询模型是否删除
        DapDataModel model = dapDataModelService.getModelById(searchRelationVo.getDataModelId());
        if(model.getBmStatus().getCode() == -1){
            return ResultBean.error("模型已被删除");
        }
        IPage<UnRelationDto> unRelationPage = dapDataModelRelatedStandardResultService.getRelationPage(searchRelationVo);
        return ResultBean.ok(unRelationPage);
    }

    @BmPermission(value = "model:table:relation:standard", name = "关联标准")
    @PostMapping("modelTable/use/relation")
    @ApiOperation("未关联标准引用(批量)")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = Boolean.class)})
    public ResultBean<Boolean> useOrIgnoreRelationStandard(@RequestBody @Valid RelationIdsVo result){

        Boolean aBoolean = dapDataModelTableFieldService.useStandard(result);
        return ResultBean.ok(aBoolean);
    }

    @BmPermission(value = "model:table:relation:standard", name = "关联标准")
    @PostMapping("modelTable/ignore/relation")
    @ApiOperation("忽略")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<Boolean> ignoreRelationStandard(@RequestBody @Valid DapDataModelRelatedStandardResult result){

        boolean b = dapDataModelRelatedStandardResultService.saveOrUpdate(result);
        // 如果是引用了标准的字段，进行忽略要删除关联关系
        dapDataModelTableFieldService.update(new LambdaUpdateWrapper<DapDataModelTableField>().
                set(DapDataModelTableField::getStandardId, "0")
                .eq(DapDataModelTableField::getId,result.getModelTableFieldId())
                .or().eq(DapDataModelTableField::getPId,result.getModelTableFieldId()));
        return ResultBean.ok(b);
    }

    @BmPermission(value = "model:table:relation:standard", name = "关联标准")
    @PostMapping("modelTable/unMatch/relation")
    @ApiOperation("未匹配/忽略列表(分页)")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = UnRelationDto.class)})
    public ResultBean<IPage<UnRelationDto>> getUnMatchStandard(@RequestBody @Valid SearchRelationVo searchRelationVo){

        // 先查询模型是否删除
        DapDataModel model = dapDataModelService.getModelById(searchRelationVo.getDataModelId());
        if(model.getBmStatus().getCode() == -1){
            return ResultBean.error("模型已被删除");
        }
        IPage<UnRelationDto> unRelationPage = dapDataModelRelatedStandardResultService.getUnMatchAndIgnore(searchRelationVo);
        return ResultBean.ok(unRelationPage);
    }

    @BmPermission(value = "model:table:list", name = "模型表查询")
    @GetMapping("/modelTable/field/json")
    @ApiOperation("获得json数据串")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<?> getDataJson(@RequestParam("modelGroupId") @ApiParam("模型分组id") String modelGroupId) {

        DapDataModelJson dapDataModelJson = dapDataModelJsonService.getBaseMapper()
                .selectOne(new LambdaQueryWrapper<DapDataModelJson>()
                .eq(DapDataModelJson::getModelGroupId, modelGroupId));
        return ResultBean.ok(dapDataModelJson);

    }

    @BmPermission(value = "model:table:list", name = "模型表查询", ignore = true)
    @PostMapping("/modelTable/field/json")
    @ApiOperation("新增/修改json数据串")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, errorMsg = "只允许模型授权者保存视图")
    @ModelEdit(keyFormClz = KeyAnnotationClz.RequestBody)
    public ResultBean<?> saveDataJson(@RequestBody DapDataModelJson dapDataModelJson) {
        // 数据入库
        dapDataModelJsonService.saveOrUpdate(dapDataModelJson);
        return ResultBean.ok(dapDataModelJson.getId());
    }

    @BmPermission(value = "model:table:copy", name = "模型表查询")
    @PostMapping("/modelTable/copy")
    @ApiOperation("复制功能")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @UserPermission.SingleRow(keyFormClz = KeyAnnotationClz.RequestBody, errorMsg = "只允许模型授权者进行复制模型表功能")
    @ModelEdit(keyFormClz = KeyAnnotationClz.RequestBody)
    public ResultBean<?> copyModelTable(@RequestBody @Valid DataModelTableInsertVO vo) {

        // 数据入库
        ResultBean<?> resultBean = dapDataModelTableService.copyTable(vo);
        return resultBean;
    }

   /* @BmPermission(value = "model:info", name = "模型表查询")
    @GetMapping("/common/model")
    @ApiOperation("查询公共模型")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    public ResultBean<DapDataModel> getCommonModel(@RequestParam("systemId") String systemId) {

        DapDataModel dapDataModel = dapDataModelService.getBaseMapper()
                .selectOne(new LambdaQueryWrapper<DapDataModel>()
                .eq(DapDataModel::getSystemId, systemId)
                .eq(DapDataModel::getCommonModel, 1)
                .eq(DapDataModel::getBmStatus, BmStatus.ON.getCode()));
        return ResultBean.ok(dapDataModel);
    }*/

    /**
     * 获取数仓模型
     *
     * @param sysId
     * @return
     */
    @GetMapping("/dwModels")
    @ApiOperation("获取数仓模型")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @BmPermission(value = "", name = "获取数仓模型", ignore = true)
    public ResultBean<List<Map<String, String>>> dwModelsBySysId(@ApiParam("系统id") @RequestParam(value = "sysId", required = false) String sysId) {
        LambdaQueryWrapper<DapDataModel> eq = dapDataModelService.bmLambdaQuery()
                .eq(StringUtils.isNotBlank(sysId), DapDataModel::getSystemId, sysId)
                .eq(DapDataModel::getSysType, 2);
        List<DapDataModel> dwModel = dapDataModelService.list(eq);
        return ResultBean.ok(dwModel)
                .convert(m -> {
                    return m.stream().map(d -> {
                        return ImmutableMap.of("id", d.getId(), "name", d.getName());
                    }).collect(Collectors.toList());
                });
    }

    /**
     * 模型id+表中英文=>表信息
     *
     * @param modelId
     * @param tbNameKeyword
     * @return
     */
    @GetMapping("/dwModelsTables")
    @ApiOperation("获取数仓模型表信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @BmPermission(value = "", name = "获取数仓模型表信息", ignore = true)
    public ResultBean<List<Map<String, String>>> dwTableByModelIdAndKeyword(@ApiParam("模型id") @RequestParam("modelId") String modelId,
                                                                            @ApiParam("关键字") @Size(max = 50, message = "最大输出长度{max}")
                                                                            @RequestParam("tbNameKeyword") String tbNameKeyword) {
        // 判断模型是否为数仓
        dapDataModelService.getByIdAsset(modelId, "模型不存在！！");
        LambdaQueryWrapper<DapDataModelTable> eq = dapDataModelTableService.bmLambdaQuery()
                .select(DapDataModelTable::getId, DapDataModelTable::getEngName)
                .eq(DapDataModelTable::getDataModelId, modelId)
                .eq(DapDataModelTable::getDataNewest, 1)
                .and(StringUtils.isNotBlank(tbNameKeyword), wrapper ->
                        wrapper.like(DapDataModelTable::getEngName, tbNameKeyword)
                                .or()
                                .like(DapDataModelTable::getName, tbNameKeyword)
                                .or()
                );
        List<DapDataModelTable> tables = dapDataModelTableService.list(eq);
        return ResultBean.ok(tables)
                .convert(m -> {
                    return m.stream().map(d -> {
                        return ImmutableMap.of("id", d.getId(), "engName", d.getEngName());
                    }).collect(Collectors.toList());
                });
    }

    /**
     * 模型id+表id=>字段信息
     *
     * @param modelId
     * @param tableId
     * @return
     */
    @GetMapping("/dwModelsTableFields")
    @ApiOperation("获取数仓模型字段信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @BmPermission(value = "", name = "获取数仓模型字段信息", ignore = true)
    public ResultBean<List<ImmutableMap<String, String>>> tbFieldsByModelIdAndTableId(@ApiParam("模型id") @RequestParam("modelId") String modelId,
                                                                                      @ApiParam("表id") @RequestParam("tableId") String tableId) {
        LambdaQueryWrapper<DapDataModelTableField> eq = dapDataModelTableFieldService.bmLambdaQuery().eq(DapDataModelTableField::getDataModelId, modelId)
                .eq(DapDataModelTableField::getModelTableId, tableId)
                .eq(DapDataModelTableField::getDataNewest, 1);
        return ResultBean.ok(dapDataModelTableFieldService.list(eq))
                .convert(m -> {
                    return m.stream().map(d -> {
                        return ImmutableMap.of("id", d.getId(), "fieldName", d.getFieldName());
                    }).collect(Collectors.toList());
                });
    }

    @GetMapping("/schema/list")
    @ApiOperation("获取数仓模型的库信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @BmPermission(value = "", name = "获取数仓模型的库信息", ignore = true)
    public ResultBean<List<String>> getSchemaList(@ApiParam("数据源id") @RequestParam("sourceId") String sourceId){
        cn.com.bluemoon.metadata.common.ResultBean<List<String>> schemaList = metaDataSchemaService.getSchemaList(sourceId, 1);
        return ResultBean.ok(schemaList.getContent());
    }

    @GetMapping("/schema/hive")
    @ApiOperation("获取数仓模型Hive的库信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @BmPermission(value = "", name = "获取数仓模型字段信息", ignore = true)
    public ResultBean<List<HiveSchemaInfoVO>> getHiveSchemaList(@ApiParam("数据源id") @RequestParam("sourceId") String sourceId,
                                                                @ApiParam("环境") @RequestParam(value = "environment", required = false, defaultValue = "1") Integer environment,
                                                                @ApiParam("schema名") @RequestParam(value = "schemaName", required = false, defaultValue = "default") String schemaName) {
        cn.com.bluemoon.metadata.common.ResultBean<List<HiveSchemaInfoVO>> schemaList = metaDataSchemaService.getHiveSchemaInfo(sourceId, environment, Collections.singletonList(schemaName));
        return ResultBean.ok(schemaList.getContent());
    }

    @GetMapping("/table/info")
    @ApiOperation("获取表详细信息")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = ResultBean.class)})
    @BmPermission(value = "", name = "获取数仓模型字段信息", ignore = true)
    public ResultBean<Boolean> getTableList(@RequestParam(value = "modelTableId") String modelTableId){
        // 查询表详细信息
        DapDataModelTable dapDataModelTable = dapDataModelTableService.getModelTableById(modelTableId);
        // 查询模型详情
        DapDataModel dapDataModel = dapDataModelService.getBaseMapper().selectById(dapDataModelTable.getDataModelId());
        // 查询系统详情
        ResultBean<DapSystemInfo> systemInfo = dapSystemInfoService.getSystemInfo(dapDataModel.getSystemId());
        if(systemInfo.getContent()==null){
            return ResultBean.error("系统信息获取失败");
        }
        // 查询数据源详情
        ResultBean<DapSystemDatasource> datasource = dapSystemDatasourceService.getDatasource(dapDataModel.getDataSourceId());
        if(datasource.getContent()==null){
            return ResultBean.error("数据源信息获取失败");
        }
        // 业务系统下的mysql,标记为入仓
        if(systemInfo.getContent().getType().equals(SystemType.BUSINESS_SYS) &&
                datasource.getContent().getDatabaseType().equals(DatabaseType.MYSQL)){
            return ResultBean.ok(true);
        }
        return ResultBean.ok(false);
    }


    @BmPermission(value = "model:table:modify", name = "编辑模型表")
    @GetMapping("import/field/list")
    @ApiOperation(value = "导入字段表")
    @ApiResponses(value = {@ApiResponse(code = 200, message = "ok", response = FieldStandardDto.class)})
    public ResultBean<List<FieldStandardDto>> fieldList(@RequestParam @ApiParam("旧表id") String oldId,
                                                        @RequestParam @ApiParam("新表id") String newId,
                                                        @RequestParam @ApiParam("新模型id") String newModelId,
                                                         @RequestParam@ApiParam("旧模型id") String oldModelId){

        // 获得模型实体
        DapDataModel dapDataModel = dapDataModelService.getBaseMapper().selectById(oldModelId);
        // 查询数据源
        ResultBean<DapSystemDatasource> datasource = dapSystemDatasourceService.getDatasource(dapDataModel.getDataSourceId());
        if(datasource.getContent()==null){
            return ResultBean.error("数据源信息获取失败，无法获得字段列表");
        }
        // 根据模型中的表id获得字段信息
        List<FieldStandardDto> fieldList = dapDataModelTableFieldService.getFieldList(oldId);
        DatabaseType type = datasource.getContent().getDatabaseType();
        if(!fieldList.isEmpty()){
            // 获得到模型id
            fieldList.forEach(f -> {
                DapDataModelTableField field = f.getField();
                field.setModelTableId(newId);
                field.setDataModelId(newModelId);
                field.setId(null);
                if(!type.equals(DatabaseType.HIVE)){
                    if(type.equals(DatabaseType.PGSQL) && field.getDataType().equals("numeric")){
                        field.setDataType("decimal");
                        field.setLength("38");
                        field.setDecimalLength(6);
                    }else {
                        field.setDataType("string");
                        field.setLength(null);
                        field.setDecimalLength(null);
                    }
                    field.setAutoIncrDefaultValue(null); 
                    field.setAutoIncrement(null);
                    field.setDefaultValue(null);
                    field.setNotNull(null);
                    field.setUnSigned(null);
                    field.setZeroFill(null);
                }
            });
        }
        return ResultBean.ok(fieldList);
    }

}

